/*****************************************************************
*	Copyright (C) Jerry. All rights reserved.
*	
*	
*	Project Name:
*
*	File Name: com_part.c
*
*	Module Name:
*
*	Description:
*		Communication port handle C file
*
*	History:
*	Name		Date			Version			Note	
*	-------		---------	--------		-----------
*	Jerry		2004-04-30	Initial version	
*	
****************************************************************/
/*------------------------- Includes --------------------------------*/
#include "stdafx.h"
#include "com_port.h"
//#include "Download.h"
#include "ModeBusCtrl.h"
#include "LogHandling.h"

/*------------------------- External variables------------------------*/

/*------------------------- External functions------------------------*/

/*------------------------- Local variables---------------------------*/
INT m_baud_rate_index = 1;		// 115200 bps.

/*------------------------- Local functions---------------------------*/
		// 230400 bps -----> 19200 bps
const T_BAUD_RATE g_baud_rate_table[5] =
{	//-- PC --PS--
	{ 230400, 5},
	{ 115200, 10 },
	{ 57600, 21 },
	{ 38400, 31 },
	{ 19200, 63 }
};

const SERIAL_PORT_PARAM g_default_port_param = { 115200, 0, 8, 0};

const COMMTIMEOUTS g_default_com_timeout = {0,0,50,1,0};//{ 0, 0, 3000, 1000, 0};

/***************************************************************
* Function Name: CCommPort::CCommPort
* Module: 
* Description: 
*	Default structure function
* 
* Arguments: 
*	None
* Return:
*	None
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
CCommPort::CCommPort()
{
	m_hPortHandle = NULL;								/* handle is NULL */
//	strcpy((char *)byPortName,(const char *)"COM1");	/* default is "COM1" */
	m_PortParam = g_default_port_param;				/* serial port parameters */
	stCommTimeOut = g_default_com_timeout;			/* communication time out */
}

/***************************************************************
* Function Name: CCommPort::CCommPort
* Module: 
* Description: 
*	Structure function
* 
* Arguments: 
*	*pPortName: Pointer of port name
* Return:
*	None
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
CCommPort::CCommPort(BYTE *pPortName)
{
	m_hPortHandle = NULL;								/* handle is NULL */
	strcpy((char *)byPortName,(const char *)pPortName);
	m_PortParam = g_default_port_param;				/* serial port parameters */
	stCommTimeOut = g_default_com_timeout;			/* communication time out */
}

/***************************************************************
* Function Name: CCommPort::CCommPort
* Module: 
* Description: 
*	Structure function
* 
* Arguments: 
*	*pPortName: Pointer of port name
*	*pstPortParam: Port parameter
* Return:
*	None
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
CCommPort::CCommPort(BYTE *pPortName, SERIAL_PORT_PARAM *pstPortParam)
{
	m_hPortHandle = NULL;								/* handle is NULL */
	strcpy((char *)byPortName,(const char *)pPortName);
	m_PortParam = *pstPortParam;					/* serial port parameters */
	stCommTimeOut = g_default_com_timeout;			/* communication time out */
}

/***************************************************************
* Function Name: CCommPort::~CCommPort
* Module: 
* Description: 
*	Release Structure function
* 
* Arguments: 
*	None
* Return:
*	None
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
CCommPort::~CCommPort()
{
	if ( m_hPortHandle ){
		ClosePort();		/* close the port */
	}
}

/***************************************************************
* Function Name: CCommPort::ClosePort
* Module: 
* Description: 
*	Close this port
* 
* Arguments: 
*	None
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
BOOL CCommPort::ClosePort()
{
	if ( m_hPortHandle ){
		CloseHandle(m_hPortHandle);		/* close the port */
		m_hPortHandle = NULL;
    }
	return TRUE;
}

/***************************************************************
* Function Name: CCommPort::ClosePort
* Module: 
* Description: 
*	Open this port
* 
* Arguments: 
*	None
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
BOOL CCommPort::OpenPort()
{
	DCB	dcb;

	char port_open_name[16];

	sprintf(port_open_name, "\\\\.\\%s", byPortName);
	//open the serial port
	m_hPortHandle=CreateFile((const char *)port_open_name,\
							GENERIC_READ|GENERIC_WRITE,\
							0,\
							NULL,\
							OPEN_EXISTING,\
							FILE_FLAG_OVERLAPPED,\
							NULL);
//	if(m_hPortHandle == NULL){
	if(m_hPortHandle == (HANDLE)0xffffffff){
		m_hPortHandle = NULL;
		return FALSE;
	}

    // set comm buffer sizes
    //
	SetupComm(m_hPortHandle,MAX_INPUT_BUF_SIZE,MAX_OUTPUT_BUF_SIZE);

    // set comm time outs
    //
	SetCommTimeouts(m_hPortHandle,&stCommTimeOut);

    // set comm state
    //
	if(!GetCommState(m_hPortHandle,&dcb)){
		CloseHandle(m_hPortHandle);
		return FALSE;
	}
	dcb.BaudRate = m_PortParam.dwBaud;
	dcb.ByteSize = m_PortParam.byDataBits;
	dcb.Parity   = m_PortParam.byParity;
	dcb.StopBits = m_PortParam.byStopBits;

	dcb.fDtrControl = DTR_CONTROL_ENABLE;	

	if(!SetCommState(m_hPortHandle,&dcb)){	// Set comm_port configure
		CloseHandle(m_hPortHandle);
		return FALSE;
	}

	return TRUE;
}

/***************************************************************
* Function Name: CCommPort::SetParam
* Module: 
* Description: 
*	Set Serial Port parameter
* 
* Arguments: 
*	stParam: Serial port Parameter
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
VOID CCommPort::SetParam(const SERIAL_PORT_PARAM &stParam)
{
	m_PortParam = stParam;
}

/***************************************************************
* Function Name: WriteDataToCom

* Module: 
* Description: 
*	Send data to DCE through Com port
* 
* Arguments: 
*	hPortHandle	:	Handle of serial port;
*	pData		:	Pointer of sending data;
*	nLen		:	Length of data.
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
INT WriteDataToCom(HANDLE	hPortHandle, BYTE *pData, INT length)
{

	BOOL fWriteStat; 
	DWORD dwWritten;
	OVERLAPPED	overlap;

	if( !length )
		return length;

	memset((void *)&overlap,0,sizeof(OVERLAPPED));

	//Clears the output buffer
	PurgeComm(hPortHandle, PURGE_TXCLEAR);
	#if UNIT_TEST
	fWriteStat=WriteFile(hPortHandle,pData,length,&dwWritten,NULL); 
	#else
	fWriteStat=WriteFile(hPortHandle,pData,length,&dwWritten,&overlap); 
	#endif
	// WriteFile return error
	if(!fWriteStat){
		if(GetLastError()!=ERROR_IO_PENDING){
			return 0;
		}
		if(!GetOverlappedResult(hPortHandle,&overlap,&dwWritten,TRUE)){
			return 0;
		}
	}
	if (dwWritten != (DWORD)length) {
		return (INT)dwWritten;
	}
	return length;

}

/***************************************************************
* Function Name: ReadDataFromCom

* Module: 
* Description: 
*	Read data from PC serial port
* 
* Arguments: 
*	hPortHandle	:	Handle of serial port;
*	pData		:	Pointer of sending data;
*	nLen		:	Length of data.
* Return:
*	Reading data length
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
INT ReadDataFromCom( HANDLE hPortHandle, BYTE *pData, INT length)
{
	DWORD lenTmp=0; 
	BOOL	fReadStat;
	OVERLAPPED	overlap;
	 CTime tm = CTime::GetCurrentTime();
	char str[200];
    CString strTime = _T(" ");
	LPTSTR pStr = strTime.GetBuffer(256);
	strTime	= tm.Format("%Y-%m-%d %H:%M:%S");

	memset((void *)&overlap,0,sizeof(OVERLAPPED));
    #if UNIT_TEST
	fReadStat=ReadFile(hPortHandle,pData,length,&lenTmp,NULL); 
	#else
	fReadStat=ReadFile(hPortHandle,pData,length,&lenTmp,&overlap);
	#endif
	if(!fReadStat){
		if(GetLastError()!=ERROR_IO_PENDING){
			return FALSE;
		}
		if(!GetOverlappedResult(hPortHandle,&overlap,&lenTmp,TRUE)){
			return FALSE;
		}
	}
    sprintf(str,"%s,%s,LINE:%d,Read data ",strTime,__FILE__,__LINE__);
	for(int i=0;i<lenTmp;i++)
	{
		sprintf(str+strlen(str),"0x%.2x ",*(pData+i));
		   
	}
	sprintf(str+strlen(str),"\r\n");
	if(lenTmp > 0)
       writeDataToLogFile(str,strlen(str));
	//appendLogToDebugWindow(str);
	return (INT)lenTmp;

}

/***************************************************************
* Function Name: ClearRxBuffer

* Module: 
* Description: 
*	Clear PC-RX buffer
* 
* Arguments: 
*	hPortHandle	:	Handle of serial port;
*
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
BOOL ClearRxBuffer( HANDLE hPortHandle )
{
	if ( !PurgeComm(hPortHandle, PURGE_RXCLEAR))
	{
		return FALSE;
	}
	return TRUE;

}

/***************************************************************
* Function Name: ClearTxBuffer

* Module: 
* Description: 
*	Clear PC-TX buffer
* 
* Arguments: 
*	hPortHandle	:	Handle of serial port;
*
* Return:
*	TRUE/FALSE
* Note:
*	
* History:
*	  Author				   Date 						Description
*	 -----------			 ---------- 					-------------
*	  
*
****************************************************************/
BOOL ClearTxBuffer( HANDLE hPortHandle )
{
	if ( !PurgeComm(hPortHandle, PURGE_TXCLEAR))
	{
		return FALSE;
	}
	return TRUE;

}
int		CCommPort::GetBufferDataCount()
{
	COMSTAT		comStat;
	DWORD		dwError;
	ClearCommError(m_hPortHandle,&dwError,&comStat);
	return comStat.cbInQue;
}
